/*
 * @Copyright: Citylife 2021
 * @Author: yu.zuo
 * @Date: 2021-03-22 10:19:35
 * @Description: 
 */

import 'dart:io';

import '../../easy_log.dart';
import '../utils.dart';

enum EasyLogFileVolumeType {
  /// Divide the volume by day
  dateDayVolume,

  /// Divide the volume into size units
  sizeVolume,

  /// Divide the volume into application startup units
  appVolume,

  /// Divided into volumes in units of days and sizes
  dateDayAndSizeVolume,
}

class EasyLogFileInfo {
  /// Whether to perform log output asynchronously.
  final bool isAsync;

  /// Volume classification methods
  final EasyLogFileVolumeType volumeType;
  const EasyLogFileInfo({this.isAsync, this.volumeType});
}

class EasyLogFileInfoDateDay extends EasyLogFileInfo {}

class EasyLogFileInfoSize extends EasyLogFileInfo {
  final int fileLength;
  const EasyLogFileInfoSize(
      {bool isAsync,
      EasyLogFileVolumeType volumeType,
      this.fileLength = 1024 * 1024 * 1})
      : super(isAsync: isAsync, volumeType: volumeType);
}

class EasyLogFileInfoApp extends EasyLogFileInfo {}

class EasyLogFileInfoDateDayAndSize extends EasyLogFileInfo {}

class EasyLogFileCache {
  final List<EasyLogRecord> caches = [];
}

class EasyLogFileAppender implements EasyLogAppender {
  static File file;
  static File createFile() {
    return file ??= File(_getFileName());
  }
  EasyLoggerConfig _config; //ref;
  EasyLogFileInfo _fileInfo;
  EasyLogFileCache _fileCache;
  File _file;
  bool _isHandleVolume = false;

  EasyLogFileAppender(this._config, {EasyLogFileVolumeType volumeType}) {
    switch (volumeType) {
      case EasyLogFileVolumeType.dateDayVolume:
        _fileInfo = EasyLogFileInfo(isAsync: false, volumeType: volumeType);
        break;
      case EasyLogFileVolumeType.sizeVolume:
        _fileInfo = EasyLogFileInfoSize(isAsync: true, volumeType: volumeType);
        _fileCache = EasyLogFileCache();
        break;
      case EasyLogFileVolumeType.appVolume:
        _fileInfo = EasyLogFileInfo(isAsync: false, volumeType: volumeType);
        break;
      case EasyLogFileVolumeType.dateDayAndSizeVolume:
        _fileInfo = EasyLogFileInfo(isAsync: true, volumeType: volumeType);
        _fileCache = EasyLogFileCache();
        break;
      default:
        throw UnimplementedError();
    }
    _file = File(_getFileName());
  }
  @override
  Future init() {
    // TODO: implement init
    throw UnimplementedError();
  }

  @override
  void logo(dynamic message) {
    if (message is EasyLogMessage) {
      String content =
          _config.formatters['EasyLogMessageFormatter'].format(message);
      logs(content);
    } else if (message is EasyLogInfo) {
      List<dynamic> contents =
          _config.formatters['EasyLogInfoFormatter'].format(message);
      List<EasyLogMessage> messages = [];
      for (var content in contents) {
        messages.add(EasyLogMessage(
            tags: {
              'appName': EasyLoggerFactory.appName,
              'logName': _config.logName.isEmpty
                  ? EasyLoggerFactory.appName
                  : _config.logName,
            },
            timestamp: fromMillisecondsSinceEpoch(),
            level: EasyLogLevel.FLAG,
            message: content));
      }
      for (var message in messages) {
        String content =
            _config.formatters['EasyLogMessageFormatter'].format(message);
        logs(content);
      }
    }
  }

  @override
  void logs(String message) {
    switch (_fileInfo.volumeType) {
      case EasyLogFileVolumeType.dateDayVolume:
        _logs(message);
        break;
      case EasyLogFileVolumeType.sizeVolume:
        _sizeLogs(message);
        break;
      case EasyLogFileVolumeType.appVolume:
        _appLogs(message);
        break;
      case EasyLogFileVolumeType.dateDayAndSizeVolume:
        _dateDayAndSizeLogs(message);
        break;
      default:
        throw UnimplementedError();
    }
  }

  @override
  Future unInit() {
    // TODO: implement unInit
    throw UnimplementedError();
  }

  void _logs(message) {
    if (false == _fileInfo.isAsync) {
      _file.writeAsStringSync(message, flush: true);
    } else {
      _file.writeAsString(message, flush: true);
    }
  }

  void _sizeLogs(message) {
    int length = _file.lengthSync(); // TODO: 如何优化
    if (length >= (_fileInfo as EasyLogFileInfoSize).fileLength) {
      _handleSizeVolume().then((int result) {}).catchError((error) {});
    }
    if (_fileCache.caches.isEmpty && false == _isHandleVolume) {
      _logs(message);
    } else {
      _fileCache.caches.add(message);
    }
  }

  void _appLogs(message) {
    _logs(message);
  }

  void _dateDayAndSizeLogs(message) {}

  /// 1.获取文件所在目录
  /// 2.关闭当前文件
  /// 3.删除符合条件的文件
  /// 4.重命名所有文件
  /// 5.创建新文件
  /// 6.打开新文件 例如： app_dev_size1.log
  Future<int> _handleSizeVolume() async {
    // var directory = _file.parent;
    // _file.close();
    // var entityList = directory.listSync();
    // var entityLength = entityList.length;
    // var path = '';
    // for (var i = 0; i < entityLength; i++) {
    //   if (0 == i) {
    //     entityList[i].deleteSync();
    //   } else {
    //     path = entityList[i].path;
    //     path = path.replaceFirst(
    //         RegExp(r'size[0-9]*\.log'), 'size${i.toString()}.log');
    //     entityList[i].renameSync(path);
    //   }
    // }
    // _file.openSync(root, appKey, uid)
  }

  static String _getFileName() {
    return null;
  }
}
